package ALBasicServer.ALProcess;

import ALBasicCommon.ALBasicCommonFun;
import ALBasicCommon.ALSerializeMaker;
import ALBasicServer.ALProcess.SynTask._AALProcessBasicMonoTask;
import ALBasicServer.ALServerSynTask.ALSynTaskManager;
import ALBasicServer.ALTask._IALSynTask;
import ALServerLog.ALServerLog;

/*****************
 * 加载步骤的管理对象
 * @author mj
 *
 */
public abstract class _AALProcess extends _AALProcessBasicMonoTask
{
	/**************
	 * 过程控制对象，所有子对象自动向父对象同步
	 * 这样父对象终止的时候各子对象也会自动终止
	 * @author mj
	 *
	 */
	public class ALProcessController 
	{
		//目前控制对象是否还有小
		protected volatile boolean _enable;
	}
	
    /// <summary>
    /// 本加载步骤的标记，用于输出日志或者在异常回调中使用
    /// </summary>
    private String _m_sProcessTag;
    /// <summary>
    /// 父节点的过程控制对象
    /// </summary>
    private _AALProcess _m_apParentProcess;
    
    //控制对象
    protected ALProcessController _m_cController;

    //是否已经开始执行，开始执行的过程不允许修改
    private boolean _m_bIsRunning;
    //是否已完成
    private boolean _m_bIsDone;

    //监控对应序列号
    private long _m_lMonitorSerialize;
    //步骤开始执行的时间
    private long _m_lProcessStartTimeMS;
    //是否超过监控时间
    private boolean _m_bIsMonitorOutTime;
    //过程控制对象的监控处理对象
    private _IALProcessMonitor _m_mMonitor;
    
    public _AALProcess(String _tag)
    {
        _m_sProcessTag = _tag;
        _m_apParentProcess = null;
        
        _m_cController = new ALProcessController();
        _m_cController._enable = true;

        _m_bIsRunning = false;
        _m_bIsDone = false;

        _m_lMonitorSerialize = 0;
        _m_lProcessStartTimeMS = 0;
        _m_bIsMonitorOutTime = false;
        _m_mMonitor = null;
    }

    public String processTag() { return _m_sProcessTag; }
    //获取从最顶层父节点获取到的标记路径
    public String getFullProcessTag()
    {
    	StringBuilder builder = new StringBuilder();
    	
    	//先放入本标记
    	builder.append(processTag());
    	
    	//逐个父节点加入
    	_AALProcess tmpProcess = _m_apParentProcess;
    	while(null != tmpProcess)
    	{
    		builder.insert(0, '/');
    		builder.insert(0, tmpProcess.processTag());
    		
    		tmpProcess = tmpProcess._m_apParentProcess;
    	}
    	
    	return builder.toString();
    }
    
    public boolean isRunning() { return _m_bIsRunning; }
    public boolean isDone() { return _m_bIsDone; }

    public long processStartTimeMS() { return _m_lProcessStartTimeMS; }
    
    public _IALProcessMonitor getMonitor() {return _m_mMonitor;}

    /// <summary>
    /// 强制刷新步骤开始时间，避免错误的监控
    /// </summary>
    protected void _forceRefreshProcessStartTime()
    {
        //生成新序列号
        _m_lMonitorSerialize = ALSerializeMaker.makeNewSerialize();
        //设置开始执行时间
        _m_lProcessStartTimeMS = ALBasicCommonFun.getNowTimeMS();
        //设置未超时
        _m_bIsMonitorOutTime = false;
    }

    /// <summary>
    /// 设置步骤标记
    /// </summary>
    /// <param name="_tag"></param>
    public void setTag(String _tag)
    {
        _m_sProcessTag = _tag;
    }

    /// <summary>
    /// 设置父节点
    /// </summary>
    /// <param name="_parentPRocess"></param>
    public void setParentProcess(_AALProcess _parentPRocess)
    {
        //判断是否原来有父对象，如果有这里有可能逻辑错误，报错
        if(null != _m_apParentProcess)
        {
            ALServerLog.Error("ALProcess Set Parent while parent already exist!");
        }

        _m_apParentProcess = _parentPRocess;
        //设置控制对象为父节点控制对象
        _m_cController = _m_apParentProcess._m_cController;
    }

    /// <summary>
    /// 进行任务的处理，这个会直接调用执行过程的处理
    /// </summary>
    @Override
    public void run()
    {
        dealProcess(_m_mMonitor);
    }
    
    /**************
     * 终止整个过程，调用本函数不会马上终止
     * 会在各执行节点上根据状态自行终止
     */
    public void stopProcess()
    {
    	if(null == _m_cController)
    		return ;
    	
    	//设置变量即可，会在流程流转的时候根据状态停止处理
    	_m_cController._enable = false;
    }

    /// <summary>
    /// 进行处理
    /// </summary>
    public void dealProcess()
    {
        dealProcess(_m_mMonitor);
    }
    /// <summary>
    /// 进行处理
    /// </summary>
    public void dealProcess(final _IALProcessMonitor _monitor)
    {
        if(_m_bIsRunning)
        {
        	ALServerLog.Error("Deal after started!");
            return;
        }
        
        //如果已经不继续执行，则直接返回
        if(!_m_cController._enable)
        {
        	//此时直接执行过程完成
        	_onProcessDone();
        	return ;
        }

        //设置开始执行
        _m_bIsRunning = true;
        _m_bIsDone = false;
        //生成新序列号
        _m_lMonitorSerialize = ALSerializeMaker.makeNewSerialize();
        //设置开始执行时间
        _m_lProcessStartTimeMS = ALBasicCommonFun.getNowTimeMS();
        //设置未超时
        _m_bIsMonitorOutTime = false;
        _m_mMonitor = _monitor;

        //获取监控时长
        long monitMaxTimeMS = 0;
        if(null != _m_mMonitor)
        {
            monitMaxTimeMS = _m_mMonitor.monitorTimeMS(processTag());

            //最多监控100秒
            if (monitMaxTimeMS > 100000)
                monitMaxTimeMS = 100000;
        }

        //只有在监控时间超过0.1秒的时候才有效
        if (monitMaxTimeMS >= 100)
        {
            final long curSerialize = _m_lMonitorSerialize;
            final long finalMonitMaxTimeMS = monitMaxTimeMS;
            //开启定时任务进行监控
            ALSynTaskManager.getInstance().regTask(
            		new _IALSynTask() {
						
						@Override
						public void run() {
		                    //序列号如果不一致则直接不处理监控
		                    if (curSerialize != _m_lMonitorSerialize)
		                        return;

		                    //计算超出监控的时间
		                    long timeoutMS = ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS - finalMonitMaxTimeMS;
		                    //已经完成且时间差在1秒以内则不进行处理，这里进行时间判断是为了避免因为计算量过大引起的超时没被捕获
		                    if (isDone() && timeoutMS < 500)
		                        return;

		                    //设置超时
		                    _m_bIsMonitorOutTime = true;
		                    //调用回调
		                    if (null != _m_mMonitor)
		                    {
		                        //如果已经完成需要调用完成的超时处理
		                        if (isDone())
		                        	_m_mMonitor.onTimeoutDone(ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS, processTag(), _processMonitorExInfo());
		                        else
			                    	_m_mMonitor.onTimeout(ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS, processTag(), _processMonitorExInfo());
		                    }
						}
					}
                , monitMaxTimeMS);
        }

        try
        {
            //执行任务
            _dealProcess(_m_mMonitor);
        }
        catch(Exception _ex)
        {
            //调用回调
            if (null != _m_mMonitor)
            	_m_mMonitor.onErr(ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS, processTag(), _processMonitorExInfo(), _ex);
        }
    }

    /// <summary>
    /// 重置处理
    /// </summary>
    public void discard()
    {
        _m_apParentProcess = null;

        _m_bIsRunning = false;
        
        _m_bIsMonitorOutTime = false;
        _m_mMonitor = null;

        _onDiscard();
    }

    /// <summary>
    /// 内部逻辑中部分脱节情况下可以在通过本函数设置monitor初始值
    /// 以此在task调用的时候设置步骤监控对象的调用方式
    /// </summary>
    @Override
    public void setMonitor(_IALProcessMonitor _monitor)
    {
        _m_mMonitor = _monitor;
    }

    //在本节点处理完成后的处理
    protected void _onProcessDone()
    {
        if(_m_bIsDone)
        {
            ALServerLog.Error("done process multi times!");
            return;
        }

        _m_bIsDone = true;

        //此时根据是否超时和监控对象是否有效进行回调调用
        if (_m_bIsMonitorOutTime && null != _m_mMonitor)
        {
            _m_mMonitor.onTimeoutDone(ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS, processTag(), _processMonitorExInfo());
        }

        //只有在有效的情况下才会执行成功回调
        if(_m_cController._enable)
        {
            //放回缓存处理
            _onDone();
        }

        //完结执行父节点的下一个处理
        if(null != _m_apParentProcess)
            _m_apParentProcess._onChildDone();
        else if(null != _m_mMonitor)
        {
        	//如果是被异常终止，需要调用对应的事件函数
        	if(!_m_cController._enable)
            	_m_mMonitor.onRootProecssStop();//在没有父节点的时候，对加农对象执行根节点完成操作
        	else
        		_m_mMonitor.onRootProecssSuc();
        		
        	_m_mMonitor.onRootProecssDone();//在没有父节点的时候，对加农对象执行根节点完成操作
        }

        //执行释放操作
        discard();
    }

    /// <summary>
    /// 获取出来可以在监控对象外围补充输出的信息
    /// </summary>
    protected abstract String _processMonitorExInfo();

    /// <summary>
    /// 执行任务
    /// </summary>
    protected abstract void _dealProcess(_IALProcessMonitor _monitor);
    /// <summary>
    /// 当子处理对象完成时的处理
    /// </summary>
    protected abstract void _onChildDone();
    /// <summary>
    /// 重置处理
    /// </summary>
    protected abstract void _onDiscard();
    /// <summary>
    /// 完成的处理
    /// </summary>
    protected abstract void _onDone();
}
